package socket

import (
	"card/app/framework/common"
	"card/app/framework/proto"
	"card/app/logic"
	"card/app/requests"
	"context"
	"github.com/pkg/errors"
	"sync"
)

type LordGame struct {
	sync.RWMutex
	playerNum int
	baseScore int
	Id        int
}

func NewLordGame(playerNum, baseScore int, id int) common.Igame {
	return &LordGame{
		playerNum: playerNum,
		baseScore: baseScore,
		Id:        id,
	}
}

func (l *LordGame) Shuffle() {

}

func (l *LordGame) GetNumber() int {
	return l.playerNum
}

func (l *LordGame) GetId() int {
	return l.Id
}

func (l *LordGame) JoinRoom(client *Client, data any) error {
	if err := roomList.CheckUserExists(client); err != nil {
		return errors.WithStack(err)
	}
	req, ok := data.(proto.JoinRoomReq)
	if !ok {
		return errors.New("加入房间数据类型错误")
	}
	_, ok1 := roomList.KickSchedules[client]
	if ok1 {
		roomList.KickSchedules[client].Stop()
		delete(roomList.KickSchedules, client)
	}
	userInfo, err := CheckLoginValid(req.Token)
	if err != nil {
		return errors.WithStack(err)
	}
	if _, ok := roomList.Room[req.RoomId]; !ok {
		return errors.New("房间不存在")
	}
	if len(roomList.Room[req.RoomId]) >= l.playerNum {
		return errors.New("房间已经满了")
	}
	client.Player = NewPlayer(userInfo, client.conn)
	roomList.Set(req.RoomId, client)
	clients, err := roomList.GetClientsExceptSelf(req.RoomId, client)
	if err != nil {
		return errors.WithStack(err)
	}
	userList := make([]proto.User, 0)
	for _, v := range clients {
		user := proto.User{
			Id:       v.Player.GetPlayerUser().ID,
			Avatar:   client.Player.GetPlayerUser().Avatar,
			Amount:   client.Player.GetPlayerUser().Amount,
			Nickname: client.Player.GetPlayerUser().Nickname,
		}
		userList = append(userList, proto.User{
			Id:       v.Player.GetPlayerUser().ID,
			Avatar:   v.Player.GetPlayerUser().Avatar,
			Amount:   v.Player.GetPlayerUser().Amount,
			Nickname: v.Player.GetPlayerUser().Nickname,
		})
		res := l.Response(user, "joinToOthers")
		v.hub.Response(res, v)

	}
	if len(userList) > 0 {
		res := l.Response(userList, "joinToSelf")
		client.hub.Response(res, client)
		l.SetIndex(client, req.RoomId)
	}
	go func() {
		roomList.AddKickScheduleEvent(req.RoomId, client)
	}()
	return nil
}

func (l *LordGame) CreateRoom(client *Client, data any) error {
	if err := roomList.CheckUserExists(client); err != nil {
		return errors.WithStack(err)
	}
	req, ok := data.(proto.CreateRoomReq)
	if !ok {
		return errors.New("创建房间数据类型错误")
	}
	userInfo, err := CheckLoginValid(req.Token)
	roomId, err := logic.NewCardRoom(context.Background()).CreateRoom(&requests.RoomRequest{
		Rule: req.Rule,
		Num:  req.Num,
	})
	if err != nil {
		return errors.WithStack(err)
	}
	client.Player = NewPlayer(userInfo, client.conn)
	roomList.Set(roomId, client)
	user := proto.User{
		Avatar:   client.Player.GetPlayerUser().Avatar,
		Amount:   client.Player.GetPlayerUser().Amount,
		Nickname: client.Player.GetPlayerUser().Nickname,
	}
	res := l.Response(user, "createRoom")
	client.hub.Response(res, client)
	l.SetIndex(client, roomId)
	return err
}

func (l *LordGame) SetIndex(client *Client, roomNum string) error {
	clients, err := roomList.GetClientsExceptSelf(roomNum, client)
	if err != nil {
		return errors.WithStack(err)
	}
	index := len(clients) + 1
	res := l.Response(proto.LordGameSetIndex{
		Index: index,
	}, "setIndex")
	client.hub.Response(res, client)
	return nil
}

func (l *LordGame) Response(data interface{}, route string) proto.Response {
	res := proto.Response{
		Route: route,
		Data:  data,
	}
	return res
}

func (l *LordGame) Ready(client *Client, data any) error {
	req, ok := data.(proto.ReadyReq)
	if !ok {
		return errors.New("准备游戏错误")
	}
	readyCount := 0
	client.Player.SetReadyStatus()
	clients, err := roomList.Get(req.RoomId)
	if err != nil {
		return errors.WithStack(err)
	}
	for _, v := range clients {
		if v.Player.GetReadyStatus() {
			readyCount++
		}
	}
	if readyCount == l.GetNumber() {

	}
	return nil
}
